home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1997 #1 / Amiga Plus Extra 1997 #1.iso / programme / tools / leoutils / words.c < prev    next >
C/C++ Source or Header  |  1996-11-25  |  7KB  |  292 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include "LeoLib.h"
  5. #if defined _AMIGA || defined AMIGA
  6. #if defined __SASC
  7. #include <proto/dos.h>
  8. #else
  9. #include <clib/dos_protos.h>
  10. #endif
  11. #include <dos/dosasl.h>
  12. #endif
  13.  
  14. #if defined _AMIGA || defined AMIGA
  15.     static char *Version="$VER:Words 2.1"
  16. #if defined __SASC
  17.     " "    "(21.11.94)" /*__AMIGADATE__*/ " ©1994 Leopold-Soft"
  18. #endif
  19. ;
  20. #endif
  21.  
  22. typedef unsigned char uchar;
  23.  
  24. typedef int bool;
  25. #define TRUE 1
  26. #define FALSE 0
  27.  
  28. static bool AddFile(char *InFile);
  29. static bool DisplayResults(char *OutFile);
  30. static bool AddWord(uchar *Word, int n);
  31.  
  32. /* In the following ansi-table, 0 = Non-word character
  33.                                 1 = May be _inside_ a word
  34.                                 2 = Actual word character, every word
  35.                                     must contain at least one of these
  36. */
  37. static uchar char_type[] = 
  38.             {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,     /* 0 */
  39.              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 1 */
  40.              0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,    /* 2 */
  41.              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 3 */
  42.              0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,    /* 4 */
  43.              2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,1,    /* 5 */
  44.              1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,    /* 6 */
  45.              2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,    /* 7 */
  46.         /*     0 1 2 3 4 5 6 7 8 9 a b c d e f     */
  47.              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 8 */
  48.              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 9 */
  49.              0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,    /* a */
  50.              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* b */
  51.              2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,    /* c */
  52.              2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,    /* d */
  53.              2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2,    /* e */
  54.              2,2,2,2,2,2,2,0,2,2,2,2,2,2,2,2};    /* f */
  55.  
  56. static void *IOBuff;
  57. static char *ProgName;
  58. static bool Verbose = FALSE;
  59.  
  60. int main(int argc, char **argv) {
  61.     static int CurrArg = 0;
  62.     static char *OutFile = NULL;
  63.     static bool FileRead = FALSE;
  64. #if defined _AMIGA || defined AMIGA
  65.     struct AnchorPath *AP;
  66.     if (!(AP = calloc(1, sizeof(struct AnchorPath) + 1024))) return 30;
  67.     AP->ap_Strlen = 1024;
  68. #endif
  69.  
  70.     ProgName = argv[0];
  71.  
  72.     if (!(IOBuff = malloc(16384))) {
  73.         fprintf(stderr, "%s: Couldn't allocate 16KB!\n", ProgName);
  74.         return 30;
  75.     }
  76.  
  77.     while(++CurrArg < argc) {
  78.         if (!strcmp(argv[CurrArg],"-o")) {
  79.             if (argc > CurrArg+1) {
  80.                 OutFile = argv[++CurrArg];
  81.                 if (Verbose) printf("Outfile set to %s...\n", OutFile);
  82.             } else {
  83.                 fprintf(stderr,"%s: -o option requires a parameter!\n", ProgName);
  84.             }
  85.         } else if (!strcmp(argv[CurrArg],"-V")) {
  86.             if (!Verbose) fprintf(stderr, "Verbose: ON\n");
  87.             Verbose = TRUE;
  88.         } else if (!strcmp(argv[CurrArg],"-v")) {
  89.             if (Verbose) fprintf(stderr, "Verbose: OFF\n");
  90.             Verbose = FALSE;
  91.         } else if (!strcmp(argv[CurrArg],"-h") || !strcmp(argv[CurrArg],"?")) {
  92.             printf("\nWords 2.1 by Henrik Herranen " __DATE__ "\n\n"
  93.                 "Usage: %s [?|-h] | [-v] | [-V] | [InFile1 [InFile2 [...]]] | [-o OutFile]\n\n"
  94.                     , ProgName);
  95.             FileRead = TRUE;
  96.         } else {
  97. #if defined _AMIGA || defined AMIGA
  98.             /* Let's do Amiga pattern matching */
  99.             if (MatchFirst(argv[CurrArg], AP)) {
  100.                 fprintf(stderr, "%s: Couldn't open %s for reading!\n", ProgName, argv[CurrArg]);
  101.                 fprintf(stderr, "%s: Failed!\n", ProgName);
  102.                 return 30;
  103.             } else {
  104.                 do {
  105.                     if (AP->ap_Info.fib_DirEntryType < 0) {
  106.                         fprintf(stderr,"%s: Sorting %s\n", ProgName, AP->ap_Buf);
  107.                         if (!AddFile(AP->ap_Buf)) {
  108.                             fprintf(stderr, "%s: Failed for %s!\n", ProgName, AP->ap_Buf);
  109.                             MatchEnd(AP);
  110.                             return 30;
  111.                         }
  112.                     } else {
  113.                         fprintf(stderr,"%s: Skipping directory %s\n", ProgName, AP->ap_Buf);
  114.                     }
  115.                 } while (!(MatchNext(AP)));
  116.                 MatchEnd(AP);
  117.             }
  118. #else
  119.             fprintf(stderr,"%s: Sorting %s\n", ProgName, argv[CurrArg]);
  120.             if (!AddFile(argv[CurrArg])) {
  121.                 fprintf(stderr, "%s: Failed for %s!\n", ProgName, argv[CurrArg]);
  122.                 return 30;
  123.             }
  124. #endif
  125.             FileRead = TRUE;
  126.         }
  127.     }
  128.  
  129.     if (!FileRead && !AddFile(NULL) || !DisplayResults(OutFile)) {
  130.         fprintf(stderr, "%s: Failed!\n", ProgName);
  131.         return 30;
  132.     }
  133.  
  134.     return 0;
  135. }
  136.  
  137.  
  138. static uchar Word[81];
  139. static int WordLen;
  140.  
  141. static bool AddFile(char *Name) {
  142.     FILE *InFile;
  143.     int origc, c;
  144.  
  145.     WordLen = 0;
  146.  
  147.     if (Name) {
  148.         if (!(InFile = fopen(Name, "ra"))) {
  149.             fprintf(stderr, "%s: Couldn't open %s for reading!\n", ProgName, Name);
  150.             return FALSE;
  151.         }
  152.         if (IOBuff) setvbuf(InFile, IOBuff, _IOFBF, (size_t) 16384);
  153.     } else {
  154.         InFile = stdin;
  155.     }
  156.  
  157.     if (Verbose) fprintf(stderr, "Reading & sorting file %s...\n", Name);
  158.  
  159.     do {
  160.         c = origc = fgetc(InFile);
  161.         if (c == -1) c = ' ';
  162.         switch (char_type[c]) {
  163.             case 0:                         /* Non-word character        */
  164.                 if (WordLen > 0) {
  165.                     while(char_type[Word[WordLen-1]] == 1) WordLen--;
  166.                     Word[WordLen] = '\000';
  167.                     if (!AddWord(Word, 1)) {
  168.                         fprintf(stderr, "%s: Out of memory!\n", ProgName);
  169.                         return FALSE;
  170.                     }
  171.                     WordLen = 0;
  172.                 }
  173.                 break;
  174.             case 1:                         /* May be _inside_ a word    */
  175.                 if (WordLen > 0 && WordLen < 80) {
  176.                     Word[WordLen++] = ToUpper(c);
  177.                 }
  178.                 break;
  179.             case 2:                         /* Actual word character    */
  180.                 if (WordLen < 80) {
  181.                     Word[WordLen++] = ToUpper(c);
  182.                 }
  183.                 break;
  184.         }
  185.     } while (origc != -1);
  186.  
  187.     if (Name) fclose(InFile);
  188.     return TRUE;
  189. }
  190.  
  191.  
  192.  
  193. struct WordNode {
  194.     struct WordNode *Next;
  195.     struct WordNode *Prev;
  196.     uchar *Word;
  197.     long Amount;
  198. };
  199.  
  200. static struct WordNode *FirstNode = NULL;
  201. long Words, Unique;
  202.  
  203.  
  204.  
  205. static struct WordNode *NewWord(uchar *Word, int n) {
  206.     static struct WordNode *tmp;
  207.     Unique++;
  208.     if (!(tmp = malloc(sizeof(struct WordNode) + strlen((char *) Word) * sizeof(uchar) + 1))) return NULL;
  209.     tmp->Prev = NULL;
  210.     tmp->Next = NULL;
  211.     tmp->Word = (uchar *) (tmp + 1);    /* Right after the structure */
  212.     tmp->Amount = n;
  213.     strcpy((char *) (tmp->Word), (char *) Word);
  214.     return tmp;
  215. }
  216.  
  217. static bool AddWordRec(uchar *Word, int n, struct WordNode *Node) {
  218.     int CmpRes = strcmp((char *) Word, (char *) (Node->Word));
  219.  
  220.     if (CmpRes < 0) {
  221.         if (!(Node->Prev)) return ((Node->Prev = NewWord(Word, n)) != NULL);
  222.         else return AddWordRec(Word, n, Node->Prev);
  223.     } else if (CmpRes > 0) {
  224.         if (!(Node->Next)) return ((Node->Next = NewWord(Word, n)) != NULL);
  225.         else return AddWordRec(Word, n, Node->Next);
  226.     } else {
  227.         Node->Amount += n;
  228.     }
  229.  
  230.     return TRUE;
  231. }
  232.  
  233. static bool AddWord(uchar *Word, int n) {
  234.     Words++;
  235.     if (!FirstNode) return ((FirstNode = NewWord(Word, n)) != NULL);
  236.     return AddWordRec(Word, n, FirstNode);
  237. }
  238.  
  239.  
  240.  
  241.  
  242. static long Largest, NewLargest, Amount;
  243. static FILE *OutFile;
  244.  
  245. static void DisplayResultsRec(struct WordNode *Node) {
  246.     if (!Node) return;
  247.  
  248.     DisplayResultsRec(Node->Prev);
  249.     if (Node->Amount > NewLargest && Node->Amount < Largest) NewLargest = Node->Amount;
  250.     else if (Node->Amount == Largest) {
  251.         int P = (Largest * 20000 / Words + 1) / 2;
  252.         fprintf(OutFile, "%1d.%02d%% %5d %s\n", P / 100, P % 100, Largest, Node->Word);
  253.         Amount++;
  254.     }
  255.     DisplayResultsRec(Node->Next);
  256. }
  257.  
  258. static bool DisplayResults(char *Name) {
  259.     if (!FirstNode) return TRUE;
  260.  
  261.     if (Name) {
  262.         if (!(OutFile = fopen(Name, "w"))) {
  263.             fprintf(stderr, "%s: Couldn't open %s for writing!\n", ProgName, Name);
  264.             return FALSE;
  265.         }
  266.         if (IOBuff) setvbuf(OutFile, IOBuff, _IOFBF, (size_t) 16384);
  267.     } else {
  268.         OutFile = stdout;
  269.     }
  270.  
  271.     fprintf(OutFile, "\nWords: %6d\nUnique: %5d\n\n", Words, Unique);
  272.  
  273.     Largest = 1<<30;    /* A huge value */
  274.  
  275.     while (Largest > 0) {
  276.         NewLargest = 0;
  277.         Amount = 0;
  278.         DisplayResultsRec(FirstNode);
  279.         if (Verbose && Largest < 1<<30) {
  280.             fprintf(stderr, "Printed %3d... %d found   \015", Largest, Amount);
  281.             fflush(stderr);
  282.         }
  283.         Largest = NewLargest;
  284.     }
  285.     if (Verbose) fprintf(stderr, "\n");
  286.  
  287.     fprintf(OutFile, "\n");
  288.  
  289.     if (Name) fclose(OutFile);
  290.     return TRUE;
  291. }
  292.